﻿
#include "VSnoWarning.h"
#include <iostream>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <windows.h>
#include <ctime>
#include <string>
using namespace std;

#define DEFAULT_PORT 5019
#define SEND_BUFF_SIZE 1024
#define RECV_BUFF_SIZE 1024

SOCKET clientSocket;

void clientRecv() {
    char recvBuff[RECV_BUFF_SIZE];
    char sendBuff[SEND_BUFF_SIZE];
    while (1) {
        // receive message from server and display
        int r = recv(clientSocket, recvBuff, RECV_BUFF_SIZE - 1, NULL);
        if (r > 0) {
            recvBuff[r] = 0;
            if (!strcmp(recvBuff, "kicked: You are kicked by admin!")) {
                cout << endl<< recvBuff << endl;
                sprintf(sendBuff, "/quit");
                send(clientSocket, sendBuff, sizeof(sendBuff), NULL);
                cout << "leaving chatroom..." << endl;
                Sleep(1000);

                // 6.Close socket
                closesocket(clientSocket);

                // 7.Cleanup protocol data
                WSACleanup();

                cout << "socket closed" << endl;

                exit(100); // client exit 
            }
            cout << endl << recvBuff << endl;
        }
    }
}

int main() {
    // 1.Determine protocol version
    WSADATA wsaData;
    int err;
    err = WSAStartup(MAKEWORD(2, 2), &wsaData); // version 2.2

    // startup check
    if (err != 0) {
        cout << "WSAStartup failed with error:" << err << endl;
        return 1;
    }
    else {
        cout << "WSAStartup success!" << endl;
    }

    // confirm version support
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        cout << "Could not find a usable version of Winsock.dll" << endl;
        WSACleanup();
        return 1;
    }
    else {
        cout << "The Winsock 2.2 dll was found okay" << endl;
    }

    // 2.Create socket
    clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // use TCP

    if (clientSocket == SOCKET_ERROR) {
        cout << "Failed to create socket: " << GetLastError() << endl;
        WSACleanup();
        return -1;
    }
    else {
        cout << "Successfully create socket!" << endl;
    }

    // 3.Get server protocol address cluster
    SOCKADDR_IN addr = { 0 };
    addr.sin_family = AF_INET;
    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    addr.sin_port = htons(DEFAULT_PORT);

    // 4.Connect to server
    int r = connect(clientSocket, (sockaddr*)&addr, sizeof addr);

    if (r == -1) {
        cout << "Failed to connect server: " << GetLastError() << endl;
        closesocket(clientSocket);
        WSACleanup();
        return -1;
    }
    else {
        cout << "Successfully connect to server!" << endl;
    }

    char username[100];
    while (1) {
        // Request and send username
        cout << "Please input your username: ";
        cin >> username;

        // admin login
        if (!strcmp(username, "admin")) {
            cout << "\nPlease enter admin password:";
            char pass[50];
            cin >> pass;
            if (!strcmp(pass, "admin123")) {
                cout << "successfully login as admin!" << endl;
                break;
            }
            else {
                cout << "wrong password!" << endl;
            }
        }
        else {
            break;
        }
    }
    send(clientSocket, username, strlen(username), NULL);

    // 5.Communication
    CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)clientRecv, NULL, NULL, NULL); // thread to receive message from server
    char sendBuff[SEND_BUFF_SIZE];
    while (1) {
        string input;
        getline(cin, input);
        strcpy(sendBuff, input.c_str());

        // exit statement
        if (!strcmp(sendBuff, "/quit")) {
            send(clientSocket, sendBuff, strlen(sendBuff), NULL);
            break;
        }
        send(clientSocket, sendBuff, strlen(sendBuff), NULL); // send to server
    }

    cout << "leaving chatroom..." << endl;

    // 6.Close socket
    closesocket(clientSocket);

    // 7.Cleanup protocol data
    WSACleanup();

    cout << "socket closed" << endl;

    return 0;
}



